#ifndef _WX_GDICMNH__
#define _WX_GDICMNH__

#include "wx/defs.h"
#include "wx/list.h"
#include "wx/string.h"
#include "wx/fontenc.h"
#include "wx/hashmap.h"
#include "wx/math.h"

class wxBitmap;
class wxBrush;
class wxColour;
class wxCursor;
class wxFont;
class wxIcon;
class wxPalette;
class wxPen;
class wxRegion;
class wxString;

enum wxBitmapType {
  wxBITMAP_TYPE_INVALID,
  wxBITMAP_TYPE_BMP,
  wxBITMAP_TYPE_BMP_RESOURCE,
  wxBITMAP_TYPE_RESOURCE = wxBITMAP_TYPE_BMP_RESOURCE,
  wxBITMAP_TYPE_ICO,
  wxBITMAP_TYPE_ICO_RESOURCE,
  wxBITMAP_TYPE_CUR,
  wxBITMAP_TYPE_CUR_RESOURCE,
  wxBITMAP_TYPE_XBM,
  wxBITMAP_TYPE_XBM_DATA,
  wxBITMAP_TYPE_XPM,
  wxBITMAP_TYPE_XPM_DATA,
  wxBITMAP_TYPE_TIF,
  wxBITMAP_TYPE_TIF_RESOURCE,
  wxBITMAP_TYPE_GIF,
  wxBITMAP_TYPE_GIF_RESOURCE,
  wxBITMAP_TYPE_PNG,
  wxBITMAP_TYPE_PNG_RESOURCE,
  wxBITMAP_TYPE_JPEG,
  wxBITMAP_TYPE_JPEG_RESOURCE,
  wxBITMAP_TYPE_PNM,
  wxBITMAP_TYPE_PNM_RESOURCE,
  wxBITMAP_TYPE_PCX,
  wxBITMAP_TYPE_PCX_RESOURCE,
  wxBITMAP_TYPE_PICT,
  wxBITMAP_TYPE_PICT_RESOURCE,
  wxBITMAP_TYPE_ICON,
  wxBITMAP_TYPE_ICON_RESOURCE,
  wxBITMAP_TYPE_ANI,
  wxBITMAP_TYPE_IFF,
  wxBITMAP_TYPE_TGA,
  wxBITMAP_TYPE_MACCURSOR,
  wxBITMAP_TYPE_MACCURSOR_RESOURCE,
  wxBITMAP_TYPE_ANY = 50
};

enum wxStockCursor {
  wxCURSOR_NONE,
  wxCURSOR_ARROW,
  wxCURSOR_RIGHT_ARROW,
  wxCURSOR_BULLSEYE,
  wxCURSOR_CHAR,
  wxCURSOR_CROSS,
  wxCURSOR_HAND,
  wxCURSOR_IBEAM,
  wxCURSOR_LEFT_BUTTON,
  wxCURSOR_MAGNIFIER,
  wxCURSOR_MIDDLE_BUTTON,
  wxCURSOR_NO_ENTRY,
  wxCURSOR_PAINT_BRUSH,
  wxCURSOR_PENCIL,
  wxCURSOR_POINT_LEFT,
  wxCURSOR_POINT_RIGHT,
  wxCURSOR_QUESTION_ARROW,
  wxCURSOR_RIGHT_BUTTON,
  wxCURSOR_SIZENESW,
  wxCURSOR_SIZENS,
  wxCURSOR_SIZENWSE,
  wxCURSOR_SIZEWE,
  wxCURSOR_SIZING,
  wxCURSOR_SPRAYCAN,
  wxCURSOR_WAIT,
  wxCURSOR_WATCH,
  wxCURSOR_BLANK,
  wxCURSOR_DEFAULT, // standard X11 cursor
  #ifdef __X__
  wxCURSOR_CROSS_REVERSE,
  wxCURSOR_DOUBLE_ARROW,
  wxCURSOR_BASED_ARROW_UP,
  wxCURSOR_BASED_ARROW_DOWN,
  #endif // X11

  wxCURSOR_ARROWWAIT,
  wxCURSOR_MAX
};

#define wxICON(X) wxIcon( (const char**) X##_xpm )
#define wxBITMAP(name) wxBitmap( (const char**) name##_xpm )

class wxSize {
  public:
    int x, y;
    wxSize() : x( 0 ), y( 0 ) { }
    wxSize( int xx, int yy ) : x( xx ), y( yy ) { }
    bool operator==( const wxSize& sz ) const { return x == sz.x && y == sz.y; }
    bool operator!=( const wxSize& sz ) const { return x != sz.x || y != sz.y; }
    wxSize operator+( const wxSize& sz ) const { return wxSize( x + sz.x, y + sz.y ); }
    wxSize operator-( const wxSize& sz ) const { return wxSize( x - sz.x, y - sz.y ); }
    wxSize operator/( int i ) const { return wxSize( x / i, y / i ); }
    wxSize operator*( int i ) const { return wxSize( x * i, y * i ); }
    wxSize& operator+=( const wxSize& sz ) { x += sz.x; y += sz.y; return *this; }
    wxSize& operator-=( const wxSize& sz ) { x -= sz.x; y -= sz.y; return *this; }
    wxSize& operator/=( const int i ) { x /= i; y /= i; return *this; }
    wxSize& operator*=( const int i ) { x *= i; y *= i; return *this; }
    void IncTo( const wxSize& sz ) { if( sz.x > x ) x = sz.x; if( sz.y > y ) y = sz.y; }
    void DecTo( const wxSize& sz ) { if( sz.x < x ) x = sz.x; if( sz.y < y ) y = sz.y; }
    void IncBy( int dx, int dy ) { x += dx; y += dy; }
    void IncBy( const wxSize& sz ) { IncBy( sz.x, sz.y ); }
    void IncBy( int d ) { IncBy( d, d ); }
    void DecBy( int dx, int dy ) { IncBy( -dx, -dy ); }
    void DecBy( const wxSize& sz ) { DecBy( sz.x, sz.y ); }
    void DecBy( int d ) { DecBy( d, d ); }
    wxSize& Scale( float xscale, float yscale ) { x = ( int )( x * xscale ); y = ( int )( y * yscale ); return *this; }
    void Set( int xx, int yy ) { x = xx; y = yy; }
    void SetWidth( int w ) { x = w; }
    void SetHeight( int h ) { y = h; }
    int GetWidth() const { return x; }
    int GetHeight() const { return y; }
    bool IsFullySpecified() const { return x != wxDefaultCoord && y != wxDefaultCoord; }
    void SetDefaults( const wxSize& size ) {
      if( x == wxDefaultCoord ) {
        x = size.x;
      }
      if( y == wxDefaultCoord ) {
        y = size.y;
      }
    }
    int GetX() const { return x; }
    int GetY() const { return y; }
};

class wxRealPoint {
  public:
    double x;
    double y;
    wxRealPoint() : x( 0.0 ), y( 0.0 ) { }
    wxRealPoint( double xx, double yy ) : x( xx ), y( yy ) { }
    wxRealPoint operator+( const wxRealPoint& pt ) const { return wxRealPoint( x + pt.x, y + pt.y ); }
    wxRealPoint operator-( const wxRealPoint& pt ) const { return wxRealPoint( x - pt.x, y - pt.y ); }
    bool operator==( const wxRealPoint& pt ) const {
      return wxIsSameDouble( x, pt.x ) && wxIsSameDouble( y, pt.y );
    }
    bool operator!=( const wxRealPoint& pt ) const { return !( *this == pt ); }
};

class wxPoint {
  public:
    int x, y;
    wxPoint() : x( 0 ), y( 0 ) { }
    wxPoint( int xx, int yy ) : x( xx ), y( yy ) { }
    bool operator==( const wxPoint& p ) const { return x == p.x && y == p.y; }
    bool operator!=( const wxPoint& p ) const { return !( *this == p ); }
    wxPoint operator+( const wxPoint& p ) const { return wxPoint( x + p.x, y + p.y ); }
    wxPoint operator-( const wxPoint& p ) const { return wxPoint( x - p.x, y - p.y ); }
    wxPoint& operator+=( const wxPoint& p ) { x += p.x; y += p.y; return *this; }
    wxPoint& operator-=( const wxPoint& p ) { x -= p.x; y -= p.y; return *this; }
    wxPoint& operator+=( const wxSize& s ) { x += s.GetWidth(); y += s.GetHeight(); return *this; }
    wxPoint& operator-=( const wxSize& s ) { x -= s.GetWidth(); y -= s.GetHeight(); return *this; }
    wxPoint operator+( const wxSize& s ) const { return wxPoint( x + s.GetWidth(), y + s.GetHeight() ); }
    wxPoint operator-( const wxSize& s ) const { return wxPoint( x - s.GetWidth(), y - s.GetHeight() ); }
    wxPoint operator-() const { return wxPoint( -x, -y ); }
};

class wxRect {
  public:
    wxRect(): x( 0 ), y( 0 ), width( 0 ), height( 0 ) { }
    wxRect( int xx, int yy, int ww, int hh ): x( xx ), y( yy ), width( ww ), height( hh ) { }
    wxRect( const wxPoint& topLeft, const wxPoint& bottomRight );
    wxRect( const wxPoint& pt, const wxSize& size ): x( pt.x ), y( pt.y ), width( size.x ), height( size.y ) { }
    wxRect( const wxSize& size ): x( 0 ), y( 0 ), width( size.x ), height( size.y ) { }
    int GetX() const { return x; }
    void SetX( int xx ) { x = xx; }
    int GetY() const { return y; }
    void SetY( int yy ) { y = yy; }
    int GetWidth() const { return width; }
    void SetWidth( int w ) { width = w; }
    int GetHeight() const { return height; }
    void SetHeight( int h ) { height = h; }
    wxPoint GetPosition() const { return wxPoint( x, y ); }
    void SetPosition( const wxPoint &p ) { x = p.x; y = p.y; }
    wxSize GetSize() const { return wxSize( width, height ); }
    void SetSize( const wxSize &s ) { width = s.GetWidth(); height = s.GetHeight(); }
    bool IsEmpty() const { return ( width <= 0 ) || ( height <= 0 ); }
    int GetLeft()   const { return x; }
    int GetTop()    const { return y; }
    int GetBottom() const { return y + height - 1; }
    int GetRight()  const { return x + width - 1; }
    void SetLeft( int left ) { x = left; }
    void SetRight( int right ) { width = right - x + 1; }
    void SetTop( int top ) { y = top; }
    void SetBottom( int bottom ) { height = bottom - y + 1; }
    wxPoint GetTopLeft() const { return GetPosition(); }
    wxPoint GetLeftTop() const { return GetTopLeft(); }
    void SetTopLeft( const wxPoint &p ) { SetPosition( p ); }
    void SetLeftTop( const wxPoint &p ) { SetTopLeft( p ); }
    wxPoint GetBottomRight() const { return wxPoint( GetRight(), GetBottom() ); }
    wxPoint GetRightBottom() const { return GetBottomRight(); }
    void SetBottomRight( const wxPoint &p ) { SetRight( p.x ); SetBottom( p.y ); }
    void SetRightBottom( const wxPoint &p ) { SetBottomRight( p ); }
    wxPoint GetTopRight() const { return wxPoint( GetRight(), GetTop() ); }
    wxPoint GetRightTop() const { return GetTopRight(); }
    void SetTopRight( const wxPoint &p ) { SetRight( p.x ); SetTop( p.y ); }
    void SetRightTop( const wxPoint &p ) { SetTopLeft( p ); }
    wxPoint GetBottomLeft() const { return wxPoint( GetLeft(), GetBottom() ); }
    wxPoint GetLeftBottom() const { return GetBottomLeft(); }
    void SetBottomLeft( const wxPoint &p ) { SetLeft( p.x ); SetBottom( p.y ); }
    void SetLeftBottom( const wxPoint &p ) { SetBottomLeft( p ); }
    wxRect& Inflate( wxCoord dx, wxCoord dy );
    wxRect& Inflate( const wxSize& d ) { return Inflate( d.x, d.y ); }
    wxRect& Inflate( wxCoord d ) { return Inflate( d, d ); }
    wxRect Inflate( wxCoord dx, wxCoord dy ) const {
      wxRect r = *this;
      r.Inflate( dx, dy );
      return r;
    }

    wxRect& Deflate( wxCoord dx, wxCoord dy ) { return Inflate( -dx, -dy ); }
    wxRect& Deflate( const wxSize& d ) { return Inflate( -d.x, -d.y ); }
    wxRect& Deflate( wxCoord d ) { return Inflate( -d ); }
    wxRect Deflate( wxCoord dx, wxCoord dy ) const {
      wxRect r = *this;
      r.Deflate( dx, dy );
      return r;
    }

    void Offset( wxCoord dx, wxCoord dy ) { x += dx; y += dy; }
    void Offset( const wxPoint& pt ) { Offset( pt.x, pt.y ); }

    wxRect& Intersect( const wxRect& rect );
    wxRect Intersect( const wxRect& rect ) const {
      wxRect r = *this;
      r.Intersect( rect );
      return r;
    }

    wxRect& Union( const wxRect& rect );
    wxRect Union( const wxRect& rect ) const {
      wxRect r = *this;
      r.Union( rect );
      return r;
    }
    bool operator==( const wxRect& rect ) const;
    bool operator!=( const wxRect& rect ) const { return !( *this == rect ); }
    bool Contains( int x, int y ) const;
    bool Contains( const wxPoint& pt ) const { return Contains( pt.x, pt.y ); }
    bool Contains( const wxRect& rect ) const;
    wxDEPRECATED( bool Inside( int x, int y ) const );
    wxDEPRECATED( bool Inside( const wxPoint& pt ) const );
    wxDEPRECATED( bool Inside( const wxRect& rect ) const );
    bool Intersects( const wxRect& rect ) const;
    wxRect operator+( const wxRect& rect ) const;
    wxRect& operator+=( const wxRect& rect ) {
      *this = *this + rect;
      return *this;
    }
    wxRect CentreIn( const wxRect& r, int dir = wxBOTH ) const {
      return wxRect( dir & wxHORIZONTAL ? r.x + ( r.width - width ) / 2 : x,
                     dir & wxVERTICAL ? r.y + ( r.height - height ) / 2 : y, width, height );
    }
    wxRect CenterIn( const wxRect& r, int dir = wxBOTH ) const {
      return CentreIn( r, dir );
    }

  public:
    int x, y, width, height;
};

inline bool wxRect::Inside( int cx, int cy ) const { return Contains( cx, cy ); }
inline bool wxRect::Inside( const wxPoint& pt ) const { return Contains( pt ); }
inline bool wxRect::Inside( const wxRect& rect ) const { return Contains( rect ); }

typedef wxInt8 wxDash;

class wxGDIObjListBase {
  public:
    wxGDIObjListBase();
    ~wxGDIObjListBase();

  protected:
    wxList list;
};

class wxPenList: public wxGDIObjListBase {
  public:
    wxPen *FindOrCreatePen( const wxColour& colour, int width, int style );
    wxDEPRECATED( void AddPen( wxPen* ) );
    wxDEPRECATED( void RemovePen( wxPen* ) );
};

class wxBrushList: public wxGDIObjListBase {
  public:
    wxBrush *FindOrCreateBrush( const wxColour& colour, int style = wxSOLID );
    wxDEPRECATED( void AddBrush( wxBrush* ) );
    wxDEPRECATED( void RemoveBrush( wxBrush* ) );
};

class wxFontList: public wxGDIObjListBase {
  public:
    wxFont *FindOrCreateFont( int pointSize, int family, int style, int weight, bool underline = false,
                              const wxString& face = wxEmptyString, wxFontEncoding encoding = wxFONTENCODING_DEFAULT );
    wxDEPRECATED( void AddFont( wxFont* ) );
    wxDEPRECATED( void RemoveFont( wxFont* ) );
};

WX_DECLARE_STRING_HASH_MAP( wxColour*, wxStringToColourHashMap );

class wxColourDatabase {
  public:
    wxColourDatabase();
    ~wxColourDatabase();
    wxColour Find( const wxString& name ) const;
    wxString FindName( const wxColour& colour ) const;
    void AddColour( const wxString& name, const wxColour& colour );
    wxDEPRECATED( wxColour *FindColour( const wxString& name ) );
    #ifdef __WXPM__
    long* m_palTable;
    size_t m_nSize;
    #endif

  private:
    void Initialize();
    wxStringToColourHashMap *m_map;
};

class wxResourceCache: public wxList {
  public:
    wxResourceCache() { }
    wxResourceCache( const unsigned int keyType ) : wxList( keyType ) { }
    virtual ~wxResourceCache();
};

extern wxPenList* wxThePenList;
extern wxBrushList* wxTheBrushList;
extern wxFontList* wxTheFontList;

class wxStockGDI {
  public:
    enum Item {
      BRUSH_BLACK,
      BRUSH_BLUE,
      BRUSH_CYAN,
      BRUSH_GREEN,
      BRUSH_GREY,
      BRUSH_LIGHTGREY,
      BRUSH_MEDIUMGREY,
      BRUSH_RED,
      BRUSH_TRANSPARENT,
      BRUSH_WHITE,
      COLOUR_BLACK,
      COLOUR_BLUE,
      COLOUR_CYAN,
      COLOUR_GREEN,
      COLOUR_LIGHTGREY,
      COLOUR_RED,
      COLOUR_WHITE,
      CURSOR_CROSS,
      CURSOR_HOURGLASS,
      CURSOR_STANDARD,
      FONT_ITALIC,
      FONT_NORMAL,
      FONT_SMALL,
      FONT_SWISS,
      PEN_BLACK,
      PEN_BLACKDASHED,
      PEN_CYAN,
      PEN_GREEN,
      PEN_GREY,
      PEN_LIGHTGREY,
      PEN_MEDIUMGREY,
      PEN_RED,
      PEN_TRANSPARENT,
      PEN_WHITE,
      ITEMCOUNT
    };

    wxStockGDI();
    virtual ~wxStockGDI();
    static void DeleteAll();
    static wxStockGDI& instance() { return *ms_instance; }
    static const wxBrush* GetBrush( Item item );
    static const wxColour* GetColour( Item item );
    static const wxCursor* GetCursor( Item item );
    virtual const wxFont* GetFont( Item item );
    static const wxPen* GetPen( Item item );
  protected:
    static wxStockGDI* ms_instance;
    static wxObject* ms_stockObject[ITEMCOUNT];
    DECLARE_NO_COPY_CLASS( wxStockGDI )
};

#define wxITALIC_FONT  wxStockGDI::instance().GetFont(wxStockGDI::FONT_ITALIC)
#define wxNORMAL_FONT  wxStockGDI::instance().GetFont(wxStockGDI::FONT_NORMAL)
#define wxSMALL_FONT   wxStockGDI::instance().GetFont(wxStockGDI::FONT_SMALL)
#define wxSWISS_FONT   wxStockGDI::instance().GetFont(wxStockGDI::FONT_SWISS)

#define wxBLACK_DASHED_PEN  wxStockGDI::GetPen(wxStockGDI::PEN_BLACKDASHED)
#define wxBLACK_PEN         wxStockGDI::GetPen(wxStockGDI::PEN_BLACK)
#define wxCYAN_PEN          wxStockGDI::GetPen(wxStockGDI::PEN_CYAN)
#define wxGREEN_PEN         wxStockGDI::GetPen(wxStockGDI::PEN_GREEN)
#define wxGREY_PEN          wxStockGDI::GetPen(wxStockGDI::PEN_GREY)
#define wxLIGHT_GREY_PEN    wxStockGDI::GetPen(wxStockGDI::PEN_LIGHTGREY)
#define wxMEDIUM_GREY_PEN   wxStockGDI::GetPen(wxStockGDI::PEN_MEDIUMGREY)
#define wxRED_PEN           wxStockGDI::GetPen(wxStockGDI::PEN_RED)
#define wxTRANSPARENT_PEN   wxStockGDI::GetPen(wxStockGDI::PEN_TRANSPARENT)
#define wxWHITE_PEN         wxStockGDI::GetPen(wxStockGDI::PEN_WHITE)

#define wxBLACK_BRUSH        wxStockGDI::GetBrush(wxStockGDI::BRUSH_BLACK)
#define wxBLUE_BRUSH         wxStockGDI::GetBrush(wxStockGDI::BRUSH_BLUE)
#define wxCYAN_BRUSH         wxStockGDI::GetBrush(wxStockGDI::BRUSH_CYAN)
#define wxGREEN_BRUSH        wxStockGDI::GetBrush(wxStockGDI::BRUSH_GREEN)
#define wxGREY_BRUSH         wxStockGDI::GetBrush(wxStockGDI::BRUSH_GREY)
#define wxLIGHT_GREY_BRUSH   wxStockGDI::GetBrush(wxStockGDI::BRUSH_LIGHTGREY)
#define wxMEDIUM_GREY_BRUSH  wxStockGDI::GetBrush(wxStockGDI::BRUSH_MEDIUMGREY)
#define wxRED_BRUSH          wxStockGDI::GetBrush(wxStockGDI::BRUSH_RED)
#define wxTRANSPARENT_BRUSH  wxStockGDI::GetBrush(wxStockGDI::BRUSH_TRANSPARENT)
#define wxWHITE_BRUSH        wxStockGDI::GetBrush(wxStockGDI::BRUSH_WHITE)

#define wxBLACK       wxStockGDI::GetColour(wxStockGDI::COLOUR_BLACK)
#define wxBLUE        wxStockGDI::GetColour(wxStockGDI::COLOUR_BLUE)
#define wxCYAN        wxStockGDI::GetColour(wxStockGDI::COLOUR_CYAN)
#define wxGREEN       wxStockGDI::GetColour(wxStockGDI::COLOUR_GREEN)
#define wxLIGHT_GREY  wxStockGDI::GetColour(wxStockGDI::COLOUR_LIGHTGREY)
#define wxRED         wxStockGDI::GetColour(wxStockGDI::COLOUR_RED)
#define wxWHITE       wxStockGDI::GetColour(wxStockGDI::COLOUR_WHITE)

#define wxCROSS_CURSOR      wxStockGDI::GetCursor(wxStockGDI::CURSOR_CROSS)
#define wxHOURGLASS_CURSOR  wxStockGDI::GetCursor(wxStockGDI::CURSOR_HOURGLASS)
#define wxSTANDARD_CURSOR   wxStockGDI::GetCursor(wxStockGDI::CURSOR_STANDARD)

extern  wxBitmap wxNullBitmap;
extern  wxIcon wxNullIcon;
extern  wxCursor wxNullCursor;
extern  wxPen wxNullPen;
extern  wxBrush wxNullBrush;
extern  wxPalette wxNullPalette;
extern  wxFont wxNullFont;
extern  wxColour wxNullColour;
extern  wxColourDatabase* wxTheColourDatabase;
extern  const wxChar wxPanelNameStr[];
extern  const wxSize wxDefaultSize;
extern  const wxPoint wxDefaultPosition;
extern void wxInitializeStockLists();
extern void wxDeleteStockLists();
extern bool wxColourDisplay();
extern int wxDisplayDepth();
#define wxGetDisplayDepth wxDisplayDepth

extern void wxDisplaySize( int *width, int *height );
extern wxSize wxGetDisplaySize();
extern void wxDisplaySizeMM( int *width, int *height );
extern wxSize wxGetDisplaySizeMM();
extern void wxClientDisplayRect( int *x, int *y, int *width, int *height );
extern wxRect wxGetClientDisplayRect();
extern void wxSetCursor( const wxCursor& cursor );

#endif
